/**
* \mainpage Media da Direcao do Movimento - ADX
*
*
*
* \section intro_sec Introducao
*
*   A finalidade deste conjunto de classes eh descrever os metodos para \n
*   o calculo da Media da Direcao do Movimento "ADX". A finalidade deste \n
*   indicador eh ajudar a determinar quando existe uma tendencia no preco da acoes.
*
* \section hist_sec Historico
*
* Foi desenvolvido e descrito em detalhes por Welles Wilder no livro: New
*  concepts in technical trading systems .
*
* @header      adx.h
* @version     2.0
* @date        26/09/2010
* @author      Alenilson Costa Oliveira <alen.brasil@gmail.com> \n
* @group       UEFS - Engenharia da Computacao
* @see         Projeto Anual I - Prof. Angelo Duarte\n Candelabro
* @link        Repositorio <http://candelabro.googlecode.com/svn/trunk/candelabro>
* @ref         Candelabro::ADX
*
*/


#include "adx.h"
#include <iostream>
#include <list>
#include <iomanip>
#include <string>
#include <fstream>
#include <cmath>

using namespace std;
using std::setiosflags;
using std::ios;



/** Construtor padrao*/
ADX::ADX()
{
}

/**
* Construtor para dados de entrada
* @param data data no formato aaaa-mm-dd
* @param altaAtual valor da alta do dia
* @param baixaAtual valor da baixa do dia
* @param fechAnt valor de fechamento do dia
*/
ADX::ADX (string data, double alta, double baixa, double fechamento)
{

    this->data = data;
    this->altaAtual = alta;
    this->baixaAtual = baixa;
    this->fechAnt = fechamento;
}

/**
* Construtor para dados de saida
* @param data data no formato aaaa-mm-dd
* @param IDpos valor do indice direcional positivo
* @param IDneg valor do indice direcional negativo
* @param resADX resultado do calculo do ADX para uma data qualquer
*/
ADX::ADX( double IDpos, double IDneg, double resADX, string datas)
{
    /** construtor para a saida de dados gerados */
    this->data = datas;
    this->IDpos = IDpos;
    this->IDneg = IDneg;
    this->resADX = resADX;
}

/// construtor para dados temporarios
ADX::ADX (string data, double dAlta, double Baixa, double indMovDirPos,
          double indMovDirNeg,double FV,double FVMed,double MDMpos,
          double MDMneg,double DX, double resADX)
{
    //construtor para dados temporarios
    this->data = data;
    this->dAlta = dAlta;
    this->dBaixa = dBaixa;
    this->indMovDirPos = indMovDirPos;
    this->indMovDirNeg = indMovDirNeg;
    this->MDMpos = MDMpos;
    this->MDMneg = MDMneg;
    this->FV = FV;
    this->FVMed = FVMed;
    this->DX = DX;
    this->resADX = resADX;

}

/** Calcula delta alta */
void ADX:: deltaAlta( double altaAtual, double altaAnt )
{
    /// Este metodo serve para setar dAlta = (alta do dia - alta anterior)
    dAlta = altaAtual - altaAnt;
}

/**  Calcula delta baixa */
void ADX:: deltaBaixa(double baixaAtual, double baixaAnt)
{
    /// Este metodo serve para setar dBaixa = (alta do dia - alta anterior)
    dBaixa= baixaAnt - baixaAtual;
}


/** Calcula o Indice de Movimento Direcional positivo ou negativo (DM+ e DM-)*/
void ADX:: indMovDir (double dAlta, double dBaixa )
{
    /// os parametros sao os deltas positivo e negativo
    /// Este metodo serve para setar indMovDirPos e indMovDirNeg

    // se os deltas forem menores q zero ou iguais entre si, o movimento � nulo
    if ( ( ( dAlta <0 ) && ( dBaixa < 0 ) ) || ( dAlta == dBaixa) )
    {
        indMovDirPos = 0;
        indMovDirNeg = 0;
    }

    // para o movimento positivo
    else if ( dAlta > dBaixa )
    {
        indMovDirPos = dAlta;
        indMovDirNeg = 0;
    }

    //para o movimento negativo
    else if ( dAlta < dBaixa )
    {
        indMovDirNeg = dBaixa;
        indMovDirPos = 0;
    }

}

/// Calcula o Indice de Movimento Direcional Medio
void ADX:: indMovDirMedio ( int n, double mdmpos, double mdmneg, double alfa )
{
    /// Average Directional Move Indicator ( ADM+ e ADM- )
    /// Este metodo serve para setar MDMpos e MDMneg

    MDMpos = ( this->indMovDirPos*alfa )+ ( (1- alfa)*mdmpos );
    MDMneg = ( this->indMovDirNeg*alfa )+ ( (1- alfa)*mdmneg );
}

/// Calcula a Faixa Verdade

void ADX:: faixaVerdade (double altaAtual, double baixaAtual, double fechAnt )
{
    /// Este metodo calcula o maior valor absoluto entre max1, max2 e max3
    double max1 = abs( (altaAtual - baixaAtual) );
    double max2 = abs( (altaAtual - fechAnt) );
    double max3 = abs( (fechAnt - baixaAtual) );

    FV = max(max1, max2);
    FV = max(max3, FV);
}


/// Calcula a Faixa Verdade Media
void ADX:: faixaVerdMedia (double n, double fvmed, double alfa )
{
    /// Este metodo serve para setar FVMed
    this->FVMed = ( this->FV*alfa )+ ( (1- alfa)*fvmed );

}

/// Calcula o indice direcional
void ADX:: indiceDirecional()
{
    /// Directional Index ( DI+ = IDpos e DI- = IDneg )

    /// Este metodo serve para setar IDpos e IDneg
    IDpos = ( (this->MDMpos * 100)/ this->FVMed );
    IDneg = ( (this->MDMneg * 100)/ this->FVMed );
}


/// Calcula o indice direcional Medio - ADX
void ADX:: movimentoDirecional()
{
    DX = ( 100*( abs((this->IDpos-this->IDneg)/(this->IDpos+this->IDneg))) );
}

void ADX:: indiceDirecionalMedio(double n, double adxAnt, double alfa )
{

    /// Apos todos os metodos serem aplicados na sequencia da classe
    /// o ADX pode ser calculado

    resADX = ( this->DX *alfa)+( (1-alfa)* adxAnt )  ;

}

/// Imprime na tela dados para teste em quatro colunas
void ADX:: imprime(string st, double a, double b, double c)
{
    /// Este metodo so serve para testes, pode ser excluido depois.
    /// So eh chamado no main para visualizacao dos dados
    cout << setiosflags( ios:: left) << setw(15) <<  st << setw(10) << a << setw(10)  << b
            <<setw(10)  << c << setw(10)  << fixed << setprecision(2) << endl;

}

/// Imprime na tela dados para teste em quatro colunas
void ADX:: imprime2(string data, double a, double b, double c, double d)
{
    /// Este metodo so serve para testes, pode ser excluido depois.
    /// So eh chamado no main para visualizacao dos dados
    cout << setiosflags( ios:: left) << setw(15) <<  data << setw(10) <<  a << setw(10)  << b
            <<setw(10)  << c << setw(10) << d << setw(10) << fixed << setprecision(3) << endl;

}
